package com.example.teaching_server.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.time.LocalTime;

/**
 * 课程表数据传输对象
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "课程表信息")
public class ScheduleDTO {

    @NotNull(message = "课程表ID不能为空")
    @Positive(message = "课程表ID必须是正整数")
    @Schema(description = "课程表记录唯一标识", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
    private Long scheduleId;

    @NotNull(message = "学期信息不能为空")
    @Schema(description = "学期信息", requiredMode = Schema.RequiredMode.REQUIRED)
    private TermDTO term;

    @NotNull(message = "星期几不能为空")
    @Min(value = 1, message = "星期几必须在1-7之间")
    @Max(value = 7, message = "星期几必须在1-7之间")
    @Schema(description = "星期几（1-7表示周一到周日）", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
    private Integer weekDay;

    @Min(value = 1, message = "周数必须大于0")
    @Max(value = 52, message = "周数不能超过52")
    @Schema(description = "第几周", example = "5")
    private Integer weekNumber;

    @JsonFormat(pattern = "yyyy-MM-dd")
    @Schema(description = "具体日期", example = "2024-03-01")
    private LocalDate specificDate;

    @NotNull(message = "时间节次不能为空")
    @Schema(description = "时间节次信息", requiredMode = Schema.RequiredMode.REQUIRED)
    private TimeSlotDTO timeSlot;

    @NotNull(message = "班级信息不能为空")
    @Schema(description = "班级信息", requiredMode = Schema.RequiredMode.REQUIRED)
    private ClassDTO classInfo;

    @NotNull(message = "课程信息不能为空")
    @Schema(description = "课程信息", requiredMode = Schema.RequiredMode.REQUIRED)
    private CourseDTO course;

    @NotNull(message = "教师信息不能为空")
    @Schema(description = "教师信息", requiredMode = Schema.RequiredMode.REQUIRED)
    private TeacherDTO teacher;

    @NotNull(message = "教室信息不能为空")
    @Schema(description = "教室信息", requiredMode = Schema.RequiredMode.REQUIRED)
    private ClassroomDTO classroom;

    @NotBlank(message = "活动类型不能为空")
    @Schema(description = "活动类型", example = "COURSE", allowableValues = {"COURSE", "MEETING", "EXAM", "ACTIVITY"}, requiredMode = Schema.RequiredMode.REQUIRED)
    private String activityType;

    @NotBlank(message = "显示名称不能为空")
    @Schema(description = "前端显示的课程/活动名称", example = "高等数学", requiredMode = Schema.RequiredMode.REQUIRED)
    private String displayName;

    @Schema(description = "课程颜色（用于前端展示）", example = "#3498db")
    private String color;

    @Schema(description = "是否可调整", example = "true")
    private Boolean adjustable;

    /**
     * 获取星期名称（前端显示用）
     */
    @Schema(description = "星期名称", accessMode = Schema.AccessMode.READ_ONLY)
    public String getWeekDayName() {
        String[] weekDays = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};
        return (weekDay != null && weekDay >= 1 && weekDay <= 7) ?
                weekDays[weekDay - 1] : "未知";
    }

    /**
     * 获取时间段字符串（前端显示用）
     */
    @Schema(description = "时间段字符串", accessMode = Schema.AccessMode.READ_ONLY)
    public String getTimeRange() {
        return (timeSlot != null && timeSlot.getStartTime() != null && timeSlot.getEndTime() != null) ?
                timeSlot.getStartTime() + "-" + timeSlot.getEndTime() : "";
    }

    /**
     * 获取课程时长（分钟）
     */
    @Schema(description = "课程时长（分钟）", accessMode = Schema.AccessMode.READ_ONLY)
    public Long getDurationMinutes() {
        if (timeSlot == null || timeSlot.getStartTime() == null || timeSlot.getEndTime() == null) {
            return 0L;
        }
        return java.time.Duration.between(timeSlot.getStartTime(), timeSlot.getEndTime()).toMinutes();
    }

    /**
     * 判断是否为当前周的课程
     */
    @Schema(description = "是否为当前周的课程", accessMode = Schema.AccessMode.READ_ONLY)
    public boolean isCurrentWeek() {
        if (specificDate == null) return false;
        LocalDate today = LocalDate.now();
        LocalDate startOfWeek = today.with(java.time.DayOfWeek.MONDAY);
        LocalDate endOfWeek = today.with(java.time.DayOfWeek.SUNDAY);
        return !specificDate.isBefore(startOfWeek) && !specificDate.isAfter(endOfWeek);
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "学期信息")
    public static class TermDTO {

        @NotNull(message = "学期ID不能为空")
        @Positive(message = "学期ID必须是正整数")
        @Schema(description = "学期唯一标识", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
        private Long termId;

        @NotBlank(message = "学期名称不能为空")
        @Schema(description = "学期名称", example = "2024年春季学期", requiredMode = Schema.RequiredMode.REQUIRED)
        private String termName;

        @NotBlank(message = "开始日期不能为空")
        @JsonFormat(pattern = "yyyy-MM-dd")
        @Schema(description = "学期开始日期", example = "2024-03-01", requiredMode = Schema.RequiredMode.REQUIRED)
        private String startDate;

        @NotBlank(message = "结束日期不能为空")
        @JsonFormat(pattern = "yyyy-MM-dd")
        @Schema(description = "学期结束日期", example = "2024-07-15", requiredMode = Schema.RequiredMode.REQUIRED)
        private String endDate;

        @NotNull(message = "是否为当前学期不能为空")
        @Schema(description = "是否为当前学期", example = "true", requiredMode = Schema.RequiredMode.REQUIRED)
        private Boolean isCurrent;

        @Schema(description = "学期状态", example = "ONGOING", allowableValues = {"UPCOMING", "ONGOING", "COMPLETED"})
        private String status;

        /**
         * 获取学期周数
         */
        @Schema(description = "学期总周数", accessMode = Schema.AccessMode.READ_ONLY)
        public Integer getTotalWeeks() {
            try {
                LocalDate start = LocalDate.parse(startDate);
                LocalDate end = LocalDate.parse(endDate);
                return (int) java.time.temporal.ChronoUnit.WEEKS.between(start, end) + 1;
            } catch (Exception e) {
                return 0;
            }
        }
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "时间节次信息")
    public static class TimeSlotDTO {

        @NotNull(message = "节次ID不能为空")
        @Positive(message = "节次ID必须是正整数")
        @Schema(description = "节次唯一标识", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
        private Long slotId;

        @NotBlank(message = "节次名称不能为空")
        @Schema(description = "节次名称", example = "第一节", requiredMode = Schema.RequiredMode.REQUIRED)
        private String slotName;

        @NotNull(message = "开始时间不能为空")
        @JsonFormat(pattern = "HH:mm")
        @Schema(description = "开始时间", example = "08:00", requiredMode = Schema.RequiredMode.REQUIRED)
        private LocalTime startTime;

        @NotNull(message = "结束时间不能为空")
        @JsonFormat(pattern = "HH:mm")
        @Schema(description = "结束时间", example = "09:40", requiredMode = Schema.RequiredMode.REQUIRED)
        private LocalTime endTime;

        @NotNull(message = "排序顺序不能为空")
        @Positive(message = "排序顺序必须是正整数")
        @Schema(description = "排序顺序", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
        private Integer sortOrder;

        @Schema(description = "节次类型", example = "MORNING", allowableValues = {"MORNING", "AFTERNOON", "EVENING"})
        private String periodType;

        /**
         * 获取节次时长描述
         */
        @Schema(description = "节次时长描述", accessMode = Schema.AccessMode.READ_ONLY)
        public String getDurationDescription() {
            if (startTime == null || endTime == null) return "";
            long minutes = java.time.Duration.between(startTime, endTime).toMinutes();
            if (minutes < 60) {
                return minutes + "分钟";
            } else {
                return (minutes / 60) + "小时" + (minutes % 60) + "分钟";
            }
        }
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "班级信息")
    public static class ClassDTO {

        @NotNull(message = "班级ID不能为空")
        @Positive(message = "班级ID必须是正整数")
        @Schema(description = "班级唯一标识", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
        private Long classId;

        @NotBlank(message = "班级名称不能为空")
        @Schema(description = "班级名称", example = "一年级一班", requiredMode = Schema.RequiredMode.REQUIRED)
        private String className;

        @NotNull(message = "年级ID不能为空")
        @Positive(message = "年级ID必须是正整数")
        @Schema(description = "年级ID", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
        private Long gradeId;

        @Schema(description = "年级名称", example = "一年级")
        private String gradeName;

        @Schema(description = "班级容量", example = "40")
        private Integer capacity;

        @Schema(description = "当前学生人数", example = "35")
        private Integer studentCount;

        /**
         * 获取完整班级名称
         */
        @Schema(description = "完整班级名称", accessMode = Schema.AccessMode.READ_ONLY)
        public String getFullClassName() {
            return (gradeName != null ? gradeName : "") +
                    (className != null ? className : "");
        }
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "课程信息")
    public static class CourseDTO {

        @NotNull(message = "课程ID不能为空")
        @Positive(message = "课程ID必须是正整数")
        @Schema(description = "课程唯一标识", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
        private Long courseId;

        @NotBlank(message = "课程名称不能为空")
        @Schema(description = "课程名称", example = "高等数学", requiredMode = Schema.RequiredMode.REQUIRED)
        private String courseName;

        @Schema(description = "课程类别", example = "必修课")
        private String category;

        @Positive(message = "学分必须为正数")
        @Schema(description = "学分", example = "4")
        private Integer credit;

        @Schema(description = "课程描述")
        private String description;

        @Schema(description = "课程代码", example = "MATH101")
        private String courseCode;

        /**
         * 获取完整课程名称
         */
        @Schema(description = "完整课程名称", accessMode = Schema.AccessMode.READ_ONLY)
        public String getFullCourseName() {
            return (courseCode != null ? courseCode + " - " : "") + courseName;
        }
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "教师信息")
    public static class TeacherDTO {

        @NotNull(message = "教师ID不能为空")
        @Positive(message = "教师ID必须是正整数")
        @Schema(description = "教师唯一标识", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
        private Long teacherId;

        @NotBlank(message = "教师姓名不能为空")
        @Schema(description = "教师姓名", example = "张老师", requiredMode = Schema.RequiredMode.REQUIRED)
        private String teacherName;

        @Schema(description = "职称", example = "高级教师")
        private String title;

        @Schema(description = "专业领域", example = "数学")
        private String specialty;

        @Schema(description = "教师工号", example = "T2024001")
        private String teacherNo;

        @Schema(description = "联系方式")
        private String contact;

        /**
         * 获取完整教师信息
         */
        @Schema(description = "完整教师信息", accessMode = Schema.AccessMode.READ_ONLY)
        public String getFullTeacherInfo() {
            return (title != null ? title : "") + teacherName +
                    (specialty != null ? " (" + specialty + ")" : "");
        }
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "教室信息")
    public static class ClassroomDTO {

        @NotNull(message = "教室ID不能为空")
        @Positive(message = "教室ID必须是正整数")
        @Schema(description = "教室唯一标识", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
        private Long classroomId;

        @NotBlank(message = "教室编号不能为空")
        @Schema(description = "教室编号", example = "201", requiredMode = Schema.RequiredMode.REQUIRED)
        private String roomNumber;

        @Schema(description = "所属楼栋", example = "教学楼A")
        private String building;

        @Positive(message = "教室容量必须为正数")
        @Schema(description = "教室容量", example = "50")
        private Integer capacity;

        @Schema(description = "教室类型", example = "普通教室")
        private String roomType;

        @Schema(description = "设备信息")
        private String equipment;

        /**
         * 获取完整教室信息
         */
        @Schema(description = "完整教室信息", accessMode = Schema.AccessMode.READ_ONLY)
        public String getFullRoomInfo() {
            return (building != null ? building : "") + roomNumber +
                    (roomType != null ? " (" + roomType + ")" : "");
        }
    }
}
